const int DHT11_PIN = 0;      // ADC0...
const int SWITCH_PIN =  13;

//Collect 8 bits from datastream, return them interpreted
//as a byte. I.e. if 0000.0101 is sent, return decimal 5.
//Code expects the system to have recently entered the
//dataline low condition at the start of every data bit's
//transmission BEFORE this function is called.
byte read_dht11_dat()
{
  byte i = 0;
  byte result=0;
  for(i=0; i< 8; i++){
  //We enter this during the first start bit (low for 50uS) of the byte
  while(!(PINC & _BV(DHT11_PIN)));  // wait until pin goes high
           //signalling end of start of bit's transmission.
  //Dataline will stay high for 27 or 70 uS, depending on if
  //   a 0 or a 1 is being sent, respectively
  delayMicroseconds(30);//AFTER pin is high, wait further period, to be
      //into the part of the timing diagram where a 0 or a 1 denotes
      //the datum being send. The "further period" was 30uS in the software
      //that this has been created from. I believe that a higher number
      //(45?) would be more appropriate.

  if(PINC & _BV(DHT11_PIN))//If pin still high
	result |=(1<<(7-i));// "add" (not just addition) the 1 to the
                //growing byte
  while((PINC & _BV(DHT11_PIN)));  // wait for pin to go low again, which
          //signals he START of the NEXT bit's transmission.
  }//end of "for.."
  return result;
}//end of "read_dht11_dat()"


void get_hum_temp()
{
	byte dht11_dat[5];
	byte dht11_in;
	byte i;

	// Send "start read and report" command to sensor....
	// 1. pull-down i/o pin for 18ms
	PORTC &= ~_BV(DHT11_PIN);
	delay(18);
        delay(5);//TKB, frm Quine at Arduino forum
        //Aosong datasheet for DHT22 says pin should be low at least
        //500us. I infer it can be low longer without any]
        //penalty apart from making "read sensor" process take
        //longer
	PORTC |= _BV(DHT11_PIN);//Bring line high again
	delayMicroseconds(40);//DHT22 datasheet says host should
           //keep line high 20-40us, then watch for sensor taking line
           //low. That low should last 80us. Acknowledges "start read
           //and report" command.

	DDRC &= ~_BV(DHT11_PIN);//Change Arduino pin to an input, to
           //watch for the 80us low explained a moment ago.
	delayMicroseconds(40);

	dht11_in = PINC & _BV(DHT11_PIN);

	if(dht11_in){
		Serial.println("dht11 start condition 1 not met");
		return;
	}
	delayMicroseconds(80);

	dht11_in = PINC & _BV(DHT11_PIN);

	if(!dht11_in){
		Serial.println("dht11 start condition 2 not met");
		return;
	}

        //After 80us low, the line should be taken high for 80us by the
        //sensor. The low following that high is the start of the first
        //bit of the forty to come. The routine "read_dht11_dat()"
        //expects to be called with the system already into this low.
	delayMicroseconds(80);
	//now ready for data reception... pick up the 5 bytes coming from
        //   the sensor
	for (i=0; i<5; i++)
		dht11_dat[i] = read_dht11_dat();

	DDRC |= _BV(DHT11_PIN);//restore pin to in?out?put duties
	PORTC |= _BV(DHT11_PIN);//re-(dis?) connect internal pullup?

        byte dht11_check_sum = dht11_dat[0]+dht11_dat[1]+dht11_dat[2]+dht11_dat[3];
	// check check_sum
	if(dht11_dat[4]!= dht11_check_sum)
        //says "if fifth byte from sensor not the same as the sum of the first four..."
	{
		Serial.println("DHT11 checksum error");
	}

	Serial.print(dht11_dat[0], DEC);
	Serial.print(".");
	Serial.print(dht11_dat[1], DEC);
	Serial.print("%  ");
	Serial.print(dht11_dat[2], DEC);
	Serial.print(".");
	Serial.print(dht11_dat[3], DEC);
	Serial.println("C");

	delay(800);//Don't try to access too frequently
}

void help_info()
{
	Serial.println("\t\tHello, I'm your house assistant!\n");
	Serial.println("\t\t1 for humidity and temperature");
	Serial.println("\t\t2 for turn on the switch");
	Serial.println("\t\t3 for turn off the switch");	
	Serial.println("\t\t4 for command help");	
}

void setup()
{
	DDRC |= _BV(DHT11_PIN);//set data pin... for now... as out(?)put
              //DDRC is data direction register for pins A0-5 are on
	PORTC |= _BV(DHT11_PIN);//(dis?)-connect internal pull up on line
              //PORTC relates to the pins A0-5 are on.

	pinMode(SWITCH_PIN, OUTPUT);
	digitalWrite(SWITCH_PIN, LOW);
	
	Serial.begin(9600);
	delay(300);//Let system settle
}



void loop()
{
	byte cmd = 0;
	
	if ( Serial.available() ) {
	   cmd = Serial.read();
  	}

	switch (cmd) {
	// no cmd
	case 0:
		break;
	// get temperature and humility
	case 1:
		get_hum_temp();
		break;
	// turn on the switch
	case 2:
		digitalWrite(SWITCH_PIN, HIGH);
		break;
	// turn off the switch
	case 3:
		digitalWrite(SWITCH_PIN, LOW);
		break;
	case 4:
		help_info();
		break;
	default:
		Serial.println("I don't know what you mean!");	
		break;
	}
}

